package com.qys.livesMall.app.user.annotation.aspecj;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qys.livesMall.app.user.annotation.entity.LimitDto;
import com.qys.livesMall.app.user.annotation.IpLimit;
import com.qys.livesMall.app.user.model.entity.IpOperateStatistics;
import com.qys.livesMall.app.user.model.entity.UserRewardConfig;
import com.qys.livesMall.app.user.service.IpOperateStatisticsService;
import com.qys.livesMall.app.user.service.UserRewardConfigService;
import com.qys.livesMall.cache.RedisCache;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.common.utils.DateUtils;
import com.qys.livesMall.common.utils.IpUtils;
import com.qys.livesMall.system.service.IH2SysConfigService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Aspect
@Component
@Slf4j
public class LimitAspect {

    @Resource
    private IH2SysConfigService configService;
    @Resource
    private RedisCache redisCache;
    @Resource
    private IpOperateStatisticsService ipOperateStatisticsService;
    @Resource
    private UserRewardConfigService userRewardConfigService;
    /**
     * 处理请求前执行
     */
/*    @Before(value = "@annotation(limit)")
    public void boBefore(JoinPoint joinPoint, IpLimit limit) {
        String combineKey = getCombineKey(limit, joinPoint);

        LimitDto entity = null;

        if (redisCache.hasKey(combineKey)) {
            entity = redisCache.getCacheObject(combineKey);
        }
        if (entity == null) {
            return;
        }
        String configKey = configService.getConfigKey(limit.key());
        if (configKey == null) {
            throw new QysException("mall_config 表未配置");
        }
        int maxCount = Integer.parseInt(configKey);
        if (maxCount <= entity.getCount()) {
            throw new QysException(limit.limitTips());
        }
    }*/
    @Before(value = "@annotation(limit)")
    public void boBefore(JoinPoint joinPoint, IpLimit limit) {
        if (ipLimitation(IpUtils.getIpAddr())) {
            throw new QysException(limit.limitTips());
        }
    }

    private Boolean ipLimitation(String ip){
        LambdaQueryWrapper<UserRewardConfig> RewardConfigwrapper=new LambdaQueryWrapper<>();
        RewardConfigwrapper.in(UserRewardConfig::getAwardType,6,7);
        List<UserRewardConfig> userRewardConfigs=userRewardConfigService.list(RewardConfigwrapper);
        if (CollectionUtils.isEmpty(userRewardConfigs)){
            return false;
        }
        Map<Integer,List<UserRewardConfig>> map = userRewardConfigs.stream().collect(Collectors.groupingBy(UserRewardConfig::getAwardType));
        List<UserRewardConfig> ipRewardConfig = map.get(6);
        if (CollectionUtils.isEmpty(ipRewardConfig)){
            return false;
        }
        List<UserRewardConfig> ips = map.get(7);
        if (CollectionUtils.isNotEmpty(ips) && ips.stream().filter(a->a.getAwardAmount().equals("1")).map(UserRewardConfig::getAwardCondition).collect(Collectors.toList()).contains(ip)){
            return false;
        }
        if (null != userRewardConfigs.get(0).getAwardUnit()){
            List<IpOperateStatistics> ipOperateStatistics= ipOperateStatisticsService.getbyIps(Arrays.asList(ip),0);
            if (CollectionUtils.isNotEmpty(ipOperateStatistics)){
                if (userRewardConfigs.get(0).getAwardUnit().compareTo(new BigDecimal(ipOperateStatistics.get(0).getNum())) <= 0){
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * 处理完请求后执行
     *
     * @param joinPoint 切点
     */
    //@AfterReturning(pointcut = "@annotation(limit)", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, IpLimit limit, Object jsonResult) {
        String combineKey = getCombineKey(limit, joinPoint);
        LimitDto entity = null;
        if (redisCache.hasKey(combineKey)) {
            entity = redisCache.getCacheObject(combineKey);
        }
        if (null == entity) {
            entity = new LimitDto();
            entity.setCount(0);
            entity.setExpirationTime(DateUtils.endOfTheDay().plusYears(1));
        }
        entity.setCount(entity.getCount() + 1);
        Duration duration = Duration.between(LocalDateTime.now(), entity.getExpirationTime());
        redisCache.setCacheObject(combineKey, entity, duration.toMinutes(), TimeUnit.MINUTES);
    }


    public String getCombineKey(IpLimit limit, JoinPoint point) {
        StringBuffer stringBuffer = new StringBuffer(limit.key());
        stringBuffer.append(IpUtils.getIpAddr()).append("-");
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        Class<?> targetClass = method.getDeclaringClass();
        stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
        return stringBuffer.toString();
    }


}
